'''
Created on 26.7.2011

@author: gilead
'''

from math import pi, sin, cos

from panda3d.core import CollisionTube,CollisionNode #@UnresolvedImport
from panda3d.core import Vec4 #@UnresolvedImport

from SingleLine import SingleLine
from Ship import Ship
from Turret import Turret

class ShipFactory(object):
    
    @staticmethod
    def CreateShip(x, y, z, guid, ownerid, typeid=1):
        if typeid == 1:
            return ShipFactory.CreateShipPanda(x, y, z, guid, ownerid)
        else:
            return None
    
    @staticmethod
    def CreateShipPanda(x, y, z, guid, ownerid):
        model = "models/panda-model"
        scale = 0.005
        model = "models/ship"
        scale = 1
        
        ship = Ship(model, guid, ownerid)
        #ship.setScale(scale, scale, scale)
        ship.setPos(x, y, z)
        
        ship.setTag('selectableObject', '1')
        cNode = ShipFactory.CreateCollisionTube('ship collision tube', ship)
        ship.attachNewNode(cNode)
        
        #ShipFactory.CreateHeadingLine(ship, 1/scale)
        #ShipFactory.CreateHeadingLine(ship, 2)
        
        ship.setColor(0,0,0,1)
        
        # TODO: tassa kohtaa pitaisi muuntaa kompassiavaruus panda3d:n avaruudeksi
        # TODO: poista tama, debuggausta varten
        x,y,z = ShipFactory.GetTurretPoint(1, 0)
        turret = ShipFactory.CreateTurret(x,y,z, 5, 5+8*18, 0)
        turret.getArc().hide()
        turret.reparentTo(ship)
        x,y,z = ShipFactory.GetTurretPoint(1, 1)
        turret = ShipFactory.CreateTurret(x,y,z, 211, 211+8*18, 1)
        turret.getArc().hide()
        turret.reparentTo(ship)
        
        return ship
    
    @staticmethod
    def GetTurretPoint(typeid, number):
        if typeid == 1:
            if number == 0:
                return 7.161,0.888,0.856
            if number == 1:
                return 7.161,-0.408,0.856
        else:
            return 0,0,0
    
    @staticmethod
    def CreateTurretPanda(x, y, z, beginAngle, endAngle, id):
        model = "models/panda-model"
        scale = 0.1
        optimal = 10000 / scale
        falloff = 2500 / scale
        
        turret = Turret(model, id, beginAngle, endAngle, optimal, falloff)
        turret.setScale(scale, scale, scale)
        turret.setPos(x, y, z)
        
        return turret
    
    @staticmethod
    def CreateTurretTower(x, y, z, beginAngle, endAngle, id):
        if id%2 == 0:
            model = "models/leftturret"
        else:
            model = "models/rightturret"
        scale = 1
        optimal = 100
        falloff = 25
        
        turret = Turret(model, id, beginAngle, endAngle, optimal, falloff)
        turret.setScale(scale, scale, scale)
        turret.setPos(x, y, z)
        
        return turret
    
    @staticmethod
    def CreateTurret(x, y, z, beginAngle, endAngle, id, typeid=1):
        if typeid == 1:
            return ShipFactory.CreateTurretTower(x, y, z, beginAngle, endAngle, id)
        else:
            return None
    
    @staticmethod
    def CreateHeadingLine(ship, length):
        # nuoli joka osoittaa aluksen suunnan
        headingLine = SingleLine(ship, 2.0, Vec4(173, 34, 34, 1))
        # mikali laivojen suunta joskus eroaa mallin nollasuunnasta,
        # ts. mallin nokka ei osoita suoraan suuntaan nolla, viivan suuntaa pitaa korjata
        deg = 0 #ship.getH()
        rad = deg * pi / 180
        yd = 10 * sin(rad) * length
        xd = 10 * cos(rad) * length
        headingLine.redraw(0,0,0,xd,yd,0)
    
    @staticmethod
    def CreateCollisionTube(name, actor):
        cNode = CollisionNode(name)
        min, max = actor.getTightBounds()
        pos = actor.getPos()
        scale = actor.getScale()
        min.setX(min.getX() / scale.getX())
        min.setY(min.getY() / scale.getY())
        min.setZ(min.getZ() / scale.getZ())
        max.setX(max.getX() / scale.getX())
        max.setY(max.getY() / scale.getY())
        max.setZ(max.getZ() / scale.getZ())
        pos.setX(pos.getX() / scale.getX())
        pos.setY(pos.getY() / scale.getY())
        pos.setZ(pos.getZ() / scale.getZ())
        
        med = (min + max) / 2

#        print pos, min, max
        
        zradius = abs(max.getZ()-min.getZ())/2
        xradius = abs(max.getX()-min.getX())/2
        # valitaan suurempi kahdesta, jostain syysta max() ei tunnu toimivan
        radius = xradius
        if zradius > radius:
            radius = zradius
        
        #cNode.addSolid(CollisionTube(pos.getX() + med.getX(), pos.getY() + min.getY(), pos.getZ() + med.getZ(), 
        #                             pos.getX() + med.getX(), pos.getY() + max.getY(), pos.getZ() + med.getZ(), radius))
        cNode.addSolid(CollisionTube(med.getX() - pos.getX(), min.getY() - pos.getY(), med.getZ() - pos.getZ(), 
                                     med.getX() - pos.getX(), max.getY() - pos.getY(), med.getZ() - pos.getZ(), radius))
        return cNode